 
import { ABaseDecision } from "GameLoop/DecisionMaking/BaseDecision";
import { CoreEntity } from "GameLoop/WorldState/EntityManager/Entitys";
import { LAB_TARGETS_BASE, LAB_TARGETS_COMBAT, LAB_TARGETS_NORMAL, t3_target_config_, T3Targets } from "utils/constants/constants";
 
import { normal_carry_max, priority } from "utils/constants/definetypes";
import { BaseMinerial } from "utils/constants/globalconstant";
 
import { LabTaskHelper } from "utils/task/LabTaskHelper";
 

/**
 * lab合成 策略
 */
export class ReactionStrategyDecision< T extends "react"="react"> extends ABaseDecision<T>
{
  
    public isExpired(event: NormalEvent, region: string): boolean 
    {
        const lordroom = Game.rooms[event.region] as Required<Room>;
        
        if(!lordroom.canExecute(150))
        {
            return false;
        }
       
        if(lordroom.controller.level<6)
        {
            return false;
        }
        const tasks = lordroom.getTaskByType("react");
        if(tasks.length>0)
        {
            return false;
        }
       //lordroom.log('error','lab 检测')
        if(lordroom.getStructures(STRUCTURE_LAB).length<3)
        {
            return false;
        }
       
        return true;
    }
    public makeTask(event: NormalEvent, region: string): IDecisionCode<T>|false
    {
        const task = this.getReactionTask(event);
        // Game.rooms[event.region].log('error','lab 检测 发布新任务任务',JSON.stringify(task))
        if(task)
        {
            return {
                region:event.region,
                isunique:false,
                task:[task as any ],
            }
        }
        return false;
    }
    private getReactionTask(event: NormalEvent,)
    {
        const room = Game.rooms[event.region];
        const coreModule = room.getEntity("CoreEntity");
        if(!room.memory.t3target)
        {
            room.memory.t3target=t3_target_config_.addition;
        }
       
        const stores =[];
        if(coreModule.Storage?.store)
        {
            stores.push(coreModule.Storage);
        }
        if(coreModule.Terminal?.store)
        {
            stores.push(coreModule.Terminal);
        }
        
        if(room.memory.t3target>=t3_target_config_.max)
        {
            {
                // 定时检测一次t3target正确数量
                const randomInex = (Math.ceil(Math.random()*1000))%T3Targets.length;
                const count = coreModule.resourceCount(T3Targets[randomInex]);
                if(coreModule.resourceCount(T3Targets[randomInex])<t3_target_config_.max)
                {
                    room.memory.t3target = count;
                }
            }
            return false;
        }
        let shortagelabtarget:Set<ResourceConstant>=  new Set();
        const component =this;
        let task = component.postSpecialLabTarget( coreModule,stores,shortagelabtarget,room.getNodeMemory().labTarget);
        
        if(task)
        {
            return   task
        }
       
        
        else if( task = component.postReactionTask(LAB_TARGETS_BASE,coreModule,stores,shortagelabtarget))
        {
            return   task
        }
        else if (task = component.postReactionTask(LAB_TARGETS_COMBAT,coreModule,stores,shortagelabtarget))
        {
            return   task
        }

        else if( task = component.postReactionTask(LAB_TARGETS_NORMAL,coreModule,stores,shortagelabtarget))
        {
            return   task
        }
        if(room.memory.t3target<t3_target_config_.max)
        {
            room.memory.t3target+=t3_target_config_.addition;
        }
         
        return false
    }


    public postSpecialLabTarget( coreModule:CoreEntity,stores:(StructureTerminal|StructureStorage)[],shortagelabtarget:Set<ResourceConstant>,target :LabTarget|undefined   )
    {
        if(target)
        {
            const task = this.postReaction(target,coreModule,stores,shortagelabtarget);
            if(task===0)
            {
                // 已经生产完成了
                coreModule.room.getNodeMemory().labTarget = undefined
             
                return false
            }
            else if(task === 1)
            {
                return false
            }
            return task;
        }
        return false;
    }

    public postReactionTask(targets:LabTarget[],coreModule:CoreEntity,stores:(StructureTerminal|StructureStorage)[],shortagelabtarget:Set<ResourceConstant>):ITaskDeclare["react"]|false
    {

        for(const labtarget of targets)
        {
            let code:0|1 | ITask<ILabTaskData<"react">>;
            const num = coreModule.room.memory.t3target;
            if(labtarget.target.length>4 && num)
            {
        
                code = this.postReaction({target:labtarget.target,number:num},coreModule,stores,shortagelabtarget);
            }
            else 
            {
                code = this.postReaction(labtarget,coreModule,stores,shortagelabtarget);
            }
          
            if(code ===0 )
            {
                continue
            }
            if(code === 1)
            {
                if(labtarget.target.length>4 && coreModule.resourceCount(labtarget.target)<3000)
                {
                    // 只买字符串长度大于3的，比如 GHO2 长度4
                    this.TryGetFromMarket(coreModule,labtarget.target,coreModule.roomName,1500);
                }

            }
            else
            {
                return code as ITask<ILabTaskData<"react">,"react">
            }
        }
        return false;
    }

    private postReaction(labtarget:LabTarget,coreModule:CoreEntity,stores:(StructureTerminal|StructureStorage)[],shortagelabtarget:Set<ResourceConstant> ):ITask<ILabTaskData<"react">,"react">|0|1
    {
        const num = coreModule.resourceCount(labtarget.target);
        if(num>labtarget.number)
        {
            // 足够则不管
            return 0;
        }
         
        // 因为lab的容量最多只有3000.所以每次只需要判断3000的量
        const  reactiontarget:LabTarget  = {target:labtarget.target,number:Math.min(labtarget.number,normal_carry_max)};
        const baseminerial = LabTaskHelper.getReactionBaseMinerial(reactiontarget);
        let isCanbeReaction = true;

        for(const minerialType in baseminerial)
        {
            const scale = baseminerial[minerialType as ResourceConstant];
            const num = coreModule.resourceCount(minerialType as ResourceConstant);
            if(num<reactiontarget.number*scale)
            {
                isCanbeReaction = false;
            }
        }

        if(isCanbeReaction)
        {
            const reactionarg = LabTaskHelper.getReactionArg(reactiontarget.target as MineralCompoundConstant,reactiontarget.number);
            const task = LabTaskHelper.createReaction(reactionarg);
            // labentity.addTask(task);
            // global.LogDebug(`${arg.entity.roomName} 投递合成任务  ${JSON.stringify(task)}`);
            if(stores.length == 2)
            {
                //
                for(let baseMaterial in baseminerial)
                {
                    const storecount = stores[1].store.getUsedCapacity(baseMaterial as MineralCompoundConstant);

                    if(storecount<reactiontarget.number)
                    {
                        coreModule.transferResource(stores[1],stores[0],[{resourceType: baseMaterial as MineralCompoundConstant,amount:storecount}],1);
                    }
                }

            }
            return task;
        }
        else
        {
            const targets = this.getShortageMinerial(reactiontarget);

            if(targets.length>0)
            {
                for(const target of targets)
                {
                    if(coreModule.resourceCount(target.target)<target.number)
                    {
                        shortagelabtarget.add(target.target);

                    }
                }
            }
        }
        return 1;
    }

    private getShortageMinerial(labtarget:LabTarget):LabTarget[]
    {
        const labtargets:LabTarget[]=[];
        const baseminerial = LabTaskHelper.getReactionBaseMinerial(labtarget);
        for(const item in baseminerial)
        {
            const scale = baseminerial[item as MineralConstant];
            if(BaseMinerial.has(item as MineralConstant))
            {
                labtargets.push({target:item as any,number:labtarget.number*scale})
            }
        }
        return labtargets;
    }
    private TryGetFromMarket(coreentity:CoreEntity,resource:MarketResourceConstant,roomName:string,amount:number )
    {
         
        // 当CR小于一定值。不不自动购买了
        if(Game.market.credits<4000000)
        {
            return false;
        }
        let energy_limit = 80000;
        if(coreentity.Terminal && coreentity.Terminal.store.getUsedCapacity(RESOURCE_ENERGY)<energy_limit)
        {
            // 能量不足就挂单买啊
            global.market.PostBuyOrder(roomName,resource,amount,0.6);

            return false;
        }
        const res =  global.market.BuyResource(roomName,resource,amount,10,0.6);
        if(!res)
        {
            global.market.PostBuyOrder(roomName,resource,amount,0.6);

        }

        return res;
    }
}